#include "win32titlebarctl.h"
#include <tchar.h>
#include <windowsx.h>

struct TitleBar
{
	TCHAR szLeft[256];
	TCHAR szCenter[256];
	TCHAR szRight[256];
	HFONT hFont;
	COLORREF crBkgnd;
	COLORREF crText;
};

static BOOL TitleBar_OnCreate(HWND hwndCtl, LPCREATESTRUCT lpCreateStruct)
{
	HGLOBAL hmem = GlobalAlloc(GHND, sizeof(struct TitleBar));
	struct TitleBar *lptb = (struct TitleBar *)(GlobalLock(hmem));
	lptb->hFont = (HFONT)GetStockObject(SYSTEM_FONT);
	lptb->crBkgnd = GetSysColor(COLOR_ACTIVECAPTION);
	lptb->crText = GetSysColor(COLOR_CAPTIONTEXT);
	GlobalUnlock(hmem);
	SetProp(hwndCtl, TEXT("TitleBarData"), hmem);
	lpCreateStruct = lpCreateStruct; // lpCreateStruct used
	return TRUE;
}

static void TitleBar_OnDestroy(HWND hwndCtl)
{
	HGLOBAL hmem = RemoveProp(hwndCtl, TEXT("TitleBarData"));
	GlobalFree(hmem);
}

static void TitleBar_OnSetFont(HWND hwndCtl, HFONT hfont, BOOL fRedraw)
{
	HGLOBAL hmem = GetProp(hwndCtl, TEXT("TitleBarData"));
	struct TitleBar *lptb = (struct TitleBar *)(GlobalLock(hmem));
	lptb->hFont = (hfont == (HFONT)NULL) ? (HFONT)GetStockObject(SYSTEM_FONT) : hfont;
	GlobalUnlock(hmem);
	if (fRedraw)
		InvalidateRect(hwndCtl, NULL, TRUE);
}

static void TitleBar_OnPaint(HWND hwndCtl)
{
	HDC hdc;
	PAINTSTRUCT ps;
	RECT rect;
	HGLOBAL hmem = GetProp(hwndCtl, TEXT("TitleBarData"));
	struct TitleBar *lptb = (struct TitleBar *)(GlobalLock(hmem));
	HBRUSH hbrBkgnd = CreateSolidBrush(lptb->crBkgnd);
	hdc = BeginPaint(hwndCtl, &ps);
	SetBkColor(hdc, lptb->crBkgnd);
	GetClientRect(hwndCtl, &rect);
	DrawFrameControl(hdc, &rect, DFC_CAPTION, 0);
	rect.left   += GetSystemMetrics(SM_CXEDGE);
	rect.right  -= GetSystemMetrics(SM_CXEDGE);
	rect.top    += GetSystemMetrics(SM_CYEDGE);
	rect.bottom -= GetSystemMetrics(SM_CYEDGE);
	FillRect(hdc, &rect, hbrBkgnd);
	rect.left += 10;
	rect.right -= 10;
	SelectObject(hdc, lptb->hFont);
	SetTextColor(hdc, lptb->crText);
	GetWindowText(hwndCtl, lptb->szLeft, 256);
	DrawText(hdc, lptb->szLeft, -1, &rect, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
	DrawText(hdc, lptb->szCenter, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
	DrawText(hdc, lptb->szRight, -1, &rect, DT_SINGLELINE | DT_RIGHT | DT_VCENTER);
	SelectObject(hdc, GetStockObject(SYSTEM_FONT));
	EndPaint(hwndCtl, &ps);
	DeleteObject(hbrBkgnd);
	GlobalUnlock(hmem);
}

/* void Cls_OnSetBkColor(HWND hwndCtl, COLORREF cr) */
#define HANDLE_TBM_SETBKCOLOR(hwnd, wParam, lParam, fn) \
    ((fn)((hwnd), (COLORREF)(wParam)), 0L)
static void TitleBar_OnSetBkColor(HWND hwndCtl, COLORREF cr)
{
	HGLOBAL hmem = GetProp(hwndCtl, TEXT("TitleBarData"));
	struct TitleBar *lptb = (struct TitleBar *)(GlobalLock(hmem));
	lptb->crBkgnd = cr;
	GlobalUnlock(hmem);
	InvalidateRect(hwndCtl, NULL, TRUE);
}

/* void Cls_OnSetTextColor(HWND hwndCtl, COLORREF cr) */
#define HANDLE_TBM_SETTEXTCOLOR(hwnd, wParam, lParam, fn) \
    ((fn)((hwnd), (COLORREF)(wParam)), 0L)
static void TitleBar_OnSetTextColor(HWND hwndCtl, COLORREF cr)
{
	HGLOBAL hmem = GetProp(hwndCtl, TEXT("TitleBarData"));
	struct TitleBar *lptb = (struct TitleBar *)(GlobalLock(hmem));
	lptb->crText = cr;
	GlobalUnlock(hmem);
	InvalidateRect(hwndCtl, NULL, TRUE);
}

/* void Cls_OnSetCenterText(HWND hwndCtl, LPCTSTR lpString) */
#define HANDLE_TBM_SETCENTER(hwnd, wParam, lParam, fn) \
    ((fn)((hwnd), (LPCTSTR)(wParam)), 0L)
static void TitleBar_OnSetCenterText(HWND hwndCtl, LPCTSTR lpString)
{
	HGLOBAL hmem = GetProp(hwndCtl, TEXT("TitleBarData"));
	struct TitleBar *lptb = (struct TitleBar *)(GlobalLock(hmem));
	_tcsncpy(lptb->szCenter, lpString, 256);
	GlobalUnlock(hmem);
	InvalidateRect(hwndCtl, NULL, TRUE);
}

/* void Cls_OnSetRightText(HWND hwndCtl, LPCTSTR lpString) */
#define HANDLE_TBM_SETRIGHT(hwnd, wParam, lParam, fn) \
    ((fn)((hwnd), (LPCTSTR)(wParam)), 0L)
static void TitleBar_OnSetRightText(HWND hwndCtl, LPCTSTR lpString)
{
	HGLOBAL hmem = GetProp(hwndCtl, TEXT("TitleBarData"));
	struct TitleBar *lptb = (struct TitleBar *)(GlobalLock(hmem));
	_tcsncpy(lptb->szRight, lpString, 256);
	GlobalUnlock(hmem);
	InvalidateRect(hwndCtl, NULL, TRUE);
}

static LRESULT CALLBACK ChildWndProc(HWND hwndCtl, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
	switch (iMsg)
	{
		HANDLE_MSG(hwndCtl, WM_CREATE, TitleBar_OnCreate);
		HANDLE_MSG(hwndCtl, WM_SETFONT, TitleBar_OnSetFont);
		HANDLE_MSG(hwndCtl, WM_PAINT, TitleBar_OnPaint);
		HANDLE_MSG(hwndCtl, TBM_SETBKCOLOR, TitleBar_OnSetBkColor);
		HANDLE_MSG(hwndCtl, TBM_SETTEXTCOLOR, TitleBar_OnSetTextColor);
		HANDLE_MSG(hwndCtl, TBM_SETCENTER, TitleBar_OnSetCenterText);
		HANDLE_MSG(hwndCtl, TBM_SETRIGHT, TitleBar_OnSetRightText);
		HANDLE_MSG(hwndCtl, WM_DESTROY, TitleBar_OnDestroy);
	}
	return DefWindowProc(hwndCtl, iMsg, wParam, lParam);
}

BOOL RegisterTitleBarControl(void)
{
	static BOOL registered = FALSE;
	WNDCLASSEX wndclass;
	if (registered == TRUE)
		return TRUE;
	wndclass.cbSize = sizeof(wndclass);
	wndclass.style = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc = ChildWndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = sizeof(struct TitleBar *);
	wndclass.hInstance = GetModuleHandle(NULL);
	wndclass.hIcon = NULL;
	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = TEXT("titlebar");
	wndclass.hIconSm = NULL;
	return registered = RegisterClassEx(&wndclass) != 0 ? TRUE : FALSE;
}
